const Router = require('koa-router');
const dayjs = require('dayjs');
const isSameOrBefore = require('dayjs/plugin/isSameOrBefore');
const Models = require('../Models/model');
const Plan = Models.getModel('plan');

let planRouter = new Router();
dayjs.extend(isSameOrBefore);

const _filter = {
	__v: 0
};

planRouter.post('/makePlan', async ctx => {
	let {
			selectedDays,
			day: timeStamp,
			override,
			...otherPlanData
		} = ctx.request.body,
		insertFailPlans = [],
		startDay = dayjs(selectedDays.value.start),
		endDay = dayjs(selectedDays.value.end),
		operationDay = startDay,
		error = false;
	while (true) {
		let currDayPlan = {
			timeStamp,
			...otherPlanData,
			executeDay: operationDay.format('YYYY-MM-DD')
		};
		if (override) {
			await insertPlanOverride(currDayPlan)
				.then(res => {
					{
						if (res && res.code === 1) error = true;
					}
				})
				.catch(err => {
					error = true;
				});
		} else {
			await insertPlan(currDayPlan)
				.then(res => {
					res ? insertFailPlans.push(currDayPlan.executeDay) : null;
				})
				.catch(err => {
					error = true;
				});
		}
		operationDay = operationDay.add(1, 'day');
		if (operationDay.isSameOrBefore(endDay.format('YYYY-MM-DD'))) continue;
		else break;
	}
	ctx.response.status = 200;
	ctx.response.body = error
		? {
			code: 1,
			msg: '服务器出错'
		  }
		: {
			code: 0,
			data: [ctx.request.body, insertFailPlans]
		  };
});

planRouter.get('/getPlan', async ctx => {
	let params = ctx.request.query,
		data = [],
		error = false;
	params.days = eval(params.days);
	if (params.days.length === 0) {
		await getAllPlans(params.user)
			.then(doc => {
				if (doc.code && doc.code === 1) {
					error = true;
				} else
					data = doc.sort((nextDay, prevDay) => {
						return compareDay(
							dayjs(nextDay.executeDay),
							dayjs(prevDay.executeDay)
						);
					});
			})
			.catch(() => {
				error = true;
			});
	} else {
		for (let i = 0; i < params.days.length; i++) {
			await getPlan({ user: params.user, day: params.days[i] })
				.then(doc => {
					if (doc.code && doc.code === 1) {
						error = true;
					} else data.push(doc);
				})
				.catch(() => {
					error = true;
				});
		}
	}

	ctx.body = error
		? {
			code: 1,
			msg: '服务器出错'
		  }
		: {
			code: 0,
			data: data
		  };
});

planRouter.post('/changeMissionState', async ctx => {
	let params = ctx.request.body,
		error = false;
	await changeMissionState(params).then(result => {
		result && result.code ? (error = true) : null;
	});
	ctx.body = error
		? {
			code: 1,
			msg: '服务器出错'
		  }
		: {
			code: 0
		  };
});

planRouter.post('/deleteMissions', async ctx => {
	let params = ctx.request.body,
		error = false;
	await deleteMission(params).then(result => {
		result && result.code ? (error = true) : null;
	});
	ctx.body = error
		? {
			code: 1,
			msg: '服务器出错'
		  }
		: {
			code: 0
		  };
});

async function deleteMission(params) {
	let result = null;
	await Plan.findById(params.planId)
		.then(async doc => {
			let newMissions = doc.missions.filter(v => {
				if (v._id == params.missionIds) {
					return false;
				}
				return true;
			});
			doc.missions = newMissions;
			await Plan.findByIdAndUpdate(params.planId, doc)
				.then(doc => {})
				.catch(() => {
					result = {
						code: 1
					};
				});
		})
		.catch(() => {
			result = {
				code: 1
			};
		});
	return result;
}

async function changeMissionState(params) {
	let result = null;
	await Plan.findById(params.planId)
		.then(async doc => {
			let newMissions = doc.missions.map(v => {
				if (v._id == params.missionIds[0]) {
					v.finished === true ? (v.finished = false) : (v.finished = true);
				}
				return v;
			});
			doc.missions = newMissions;
			await Plan.findByIdAndUpdate(params.planId, doc)
				.then(doc => {})
				.catch(() => {
					result = {
						code: 1
					};
				});
		})
		.catch(() => {
			result = {
				code: 1
			};
		});
	return result;
}

async function getPlan(data) {
	let plan = null;
	await Plan.findOne({ user: data.user, executeDay: data.day }, _filter)
		.then(doc => {
			plan = doc;
		})
		.catch(() => {
			{
				plan = {
					code: 1
				};
			}
		});
	return plan;
}

async function getAllPlans(data) {
	let plans = null;
	await Plan.find({ user: data }, _filter, (err, doc) => {
		if (err)
			plans = {
				code: 1
			};
		else plans = doc;
	}).limit(100);
	return plans;
}

async function insertPlan(data) {
	let existPlan = false;
	await Plan.findOne(
		{ user: data.user, executeDay: data.executeDay },
		(err, doc) => {
			if (err) {
				existPlan = {
					code: 1
				};
			} else if (doc === null) {
				Plan.create(data);
			} else {
				existPlan = true;
			}
		}
	);
	return existPlan;
}

async function insertPlanOverride(data) {
	let resData = null;
	await Plan.findOneAndUpdate(
		{ user: data.user, executeDay: data.executeDay },
		data,
		err => {
			if (err) {
				resData = {
					code: 1
				};
			}
		}
	);
	return resData;
}

function compareDay(nextDay, prevDay) {
	if (nextDay.isSameOrBefore(prevDay)) return 1;
	else return -1;
}

module.exports = planRouter;
